//
// Ephi - simulation of magnetic fields and particles
// Copyright (C) 2007 Indrek Mandre <indrek(at)mare.ee>
// For more information please see http://www.mare.ee/indrek/ephi/
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "ephi.hpp"

// an electron oscillating around a sphere of uniform positive charge (potential well)

#define TIME_TO_RUN (2e-5)
#define SPEED 100
#define CURRENT 6000.0
#define RADIUS 0.2
#define ERADIUS 0.5

int main (int argc, char *argv[])
{
  Statics statics;
  ElectroDynamics dyn(statics);
  statics.addStaticElement (new StaticUniformSphere (vect3d(0, 0, 0), ERADIUS, 1e-7));
  //statics.addStaticElement (new StaticRing(CURRENT, vect3d(0, 0, 0), RADIUS, 0, vect3d(0.0, 0.0, 1.0)));

  dyn.inject_electron (vect3d(-1.5, 0, 0), vect3d(0.1, 0.1, 0), SPEED);
  dyn.setDTM (0.01); // don't want to wait too long

  Screen screen(800, 800, 4.0, 4.0);
  screen.draw_axes();

  statics.draw (screen, Screen::BLACK);

#define PIXEL_INTERVAL 0.0000000005
  prec_t cp = 0;

  prec_t mid_pot = statics.getPotential (vect3d(0, 0, 0));

  prec_t start_pot = mid_pot - statics.getPotential (dyn.get_pos(0)) +
      ElectroDynamics::ms2eV(dyn.get_v(0).length(), ELECTRON_MASS);

  size_t n = 0;
  while ( true )
    {
      prec_t et = dyn.get_elapsed_time ();
      if ( et >= cp )
        {
          screen.set_pixel (dyn.get_pos(0), Screen::RED);
          cp += PIXEL_INTERVAL;
          fprintf (stderr, "\rCalculating: %.2f%%", prec2double(100.0 * dyn.get_elapsed_time() / TIME_TO_RUN));
          fflush (stderr);
//          dyn.print();
        }

      if ( et >= TIME_TO_RUN )
          break;

#if 0
      if ( !(n % 1000) )
        {
          prec_t poten = mid_pot - statics.getPotential (dyn.get_pos(0));
          prec_t sen = ElectroDynamics::ms2eV(dyn.get_v(0).length(), ELECTRON_MASS);
          printf ("Energy: pot=%f, self=%f, total=%f\n", poten, sen, poten + sen);
        }
#endif
      dyn.step ();
      n++;
    }
  fprintf (stderr, "\r                            \r");
  fflush (stderr);

  screen.write ("test18.bmp");

  prec_t end_pot = mid_pot - statics.getPotential (dyn.get_pos(0)) +
      ElectroDynamics::ms2eV(dyn.get_v(0).length(), ELECTRON_MASS);
  prec_t diff = fabs (start_pot - end_pot);
  if ( diff > start_pot / 1000 )
      printf ("ERROR=speed changed significantly, what gives?\n");
  else
      printf ("OK=generated test18.bmp\n");

  return 0;
}

